﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PGMHelper;
using System.IO;
using System.Windows.Forms.DataVisualization.Charting;

namespace HystereticBasic
{
    /// <summary>
    /// 力位移值
    /// </summary>
    public class ForceDispBasicPair
    {
        #region Variables

        /// <summary>
        /// 力
        /// </summary>
        public float Force { set; get; }

        /// <summary>
        /// 位移
        /// </summary>
        public float Disp { set; get; }

        /// <summary>
        /// 编号
        /// </summary>
        public int Order { set; get; }

        #endregion

        /// <summary>
        /// 割线刚度
        /// </summary>
        public float SecantStiffness
        {
            get
            {
                return this.Disp == 0 ? 0 : Math.Abs(Force / Disp);
            }
        }

        /// <summary>
        /// 两个点间线性插值多个点
        /// </summary>
        /// <param name="prtJ"></param>
        /// <param name="deltaDisp"></param>
        /// <returns></returns>
        public MontForceDispObj GetMontForceDispObj(ForceDispBasicPair prtJ, float deltaDisp)
        {
            //初始化
            var obj = new MontForceDispObj();
            //如果增量为零
            if (Math.Abs(deltaDisp) < GlobalParam.DispTol)
                return new MontForceDispObj(this);
            //计算数据点数目
            var prtNum = Math.Abs((int)((prtJ.Disp - this.Disp) / deltaDisp));
            //求斜率
            var slope = this.GetStiffness(prtJ);
            //增加数据点
            for (int i = 0; i < prtNum; i++)
            {
                var disp = this.Disp + i * deltaDisp;
                var force = this.Force + slope * i * deltaDisp;
                obj.Add(new ForceDispBasicPair(disp, force));
            }
            //添加最后数据点
            obj.Add(prtJ);
            return obj;
        }

        /// <summary>
        /// 获得三角形面积
        /// 用于计算等效阻尼系数
        /// </summary>
        public float GetA()
        {
            return (this.Force * this.Disp < 0) ? 0: this.Force * this.Disp * 0.5F;
        }

        /// <summary>
        /// 是否相同点
        /// </summary>
        /// <param name="pt"></param>
        /// <returns></returns>
        public bool isSamePt(ForceDispBasicPair pt)
        {
            return (Math.Abs(this.Force - pt.Force) < GlobalParam.ForceTol) &&
                (Math.Abs(this.Disp - pt.Disp) < GlobalParam.DispTol);
        }

        /// <summary>
        /// 计算能量
        /// </summary>
        /// <param name="preForceDisp"></param>
        public float GetEnergy(ForceDispBasicPair prtI)
        {
            //位移增量
            var deltaDisp = (this.Disp - prtI.Disp);
            //返回能量
            return (this.Force + prtI.Force) * deltaDisp * 0.5F;
        }

        /// <summary>
        /// 求两点刚度
        /// </summary>
        /// <param name="prtJ"></param>
        /// <returns></returns>
        public float GetStiffness(ForceDispBasicPair prtJ)
        {
            return (prtJ.Force - this.Force) / (prtJ.Disp - this.Disp);
        }

        /// <summary>
        /// 计算点于点距离
        /// </summary>
        /// <param name="prtJ"></param>
        /// <returns></returns>
        public float GetDistance(ForceDispBasicPair prtJ)
        {
            return (float)Math.Sqrt(Math.Pow(prtJ.Disp - this.Disp, 2) + Math.Pow(prtJ.Force - this.Force, 2));
        }

        /// <summary>
        /// 差值数据点
        /// </summary>
        /// <param name="ptJ"></param>
        /// <param name="force"></param>
        /// <param name="targetPt"></param>
        /// <returns></returns>
        public bool GetInterpolationPt(ForceDispBasicPair ptJ,
            float force, out ForceDispBasicPair targetPt)
        {
            //初始化
            targetPt = new ForceDispBasicPair();
            //位移增量
            var deltaDisp = ptJ.Disp - this.Disp;
            //位移增量为零
            if (deltaDisp == 0) return false;
            //斜率
            var slope = this.GetStiffness(ptJ);
            //计算位移
            var disp = this.Disp - ((this.Force - force) / slope);
            //获得点
            targetPt = new ForceDispBasicPair(disp, force);
            return true;
        }

        /// <summary>
        /// 差值数据点
        /// </summary>
        /// <param name="ptJ"></param>
        /// <param name="force"></param>
        /// <param name="targetPt"></param>
        /// <returns></returns>
        private bool GetInterpolationPtInLine(ForceDispBasicPair ptJ, 
            float force, out ForceDispBasicPair targetPt)
        {
            //初始化
            targetPt = new ForceDispBasicPair();
            //点同向
            if ((this.Force - force) * (ptJ.Force - force) > 0) 
                return false;
            //点插值
            return this.GetInterpolationPt(ptJ, force, out targetPt);
        }

        /// <summary>
        /// 差值数据点
        /// </summary>
        /// <param name="ptJ"></param>
        /// <param name="force"></param>
        /// <param name="targetPt"></param>
        /// <returns></returns>
        public bool GetZeroForcePtInLine(ForceDispBasicPair ptJ, out ForceDispBasicPair targetPt)
        {
            return this.GetInterpolationPtInLine(ptJ, 0, out targetPt);
        }

        #region 构造函数

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="order"></param>
        /// <param name="disp"></param>
        /// <param name="force"></param>
        public ForceDispBasicPair(int order, float disp, float force)
        {
            this.Force = force;
            this.Disp = disp;
            this.Order = order;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="force"></param>
        /// <param name="disp"></param>
        public ForceDispBasicPair(float disp, float force)
            :this(-1, disp, force)
        {
            
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="pair"></param>
        public ForceDispBasicPair(ForceDispBasicPair pair)
        {
            this.Force = pair.Force;
            this.Disp = pair.Disp;
            this.Order = pair.Order;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        public ForceDispBasicPair()
        {
            this.Order = -1;
            this.Disp = 0;
            this.Force = 0;
        }

        #endregion
    }


}
